// 枚举属性
// enum color {
//     RED ,
//     BLUE,
//     yellow = 10,
//     pink
// }
// console.log(color.RED)   // 0
// console.log(color[0])   // RED

// enum names {
//     MY = 'cjq'
// }
// console.log(names.MY)  //cjq

// 数组
// const arr: number[] = [1, 2, 3]
// const arr2 : Array<number> = [1, 2, 3]

// 元组
// const flag: [string, number] = ['hello', 1]

// let u: undefined = undefined;
// let n: null = null;

// let value: unknown

// value = true //ok
// value = 42  //ok
// let value1: unknown = value; // OK
// let value2: any = value; // OK
// let value3: boolean = value; // Error
// let value4: number = value; // Error
// let value5: string = value; // Error
// let value6: object = value; // Error

// function hello (name: string): void {

// }
// hello('s')

// const fn = (): never => {
//     throw new Error('sss')
// }

//Object 和 object 和 {}

// let objCase: Object 
// objCase = 1  //  ok
// objCase = 'str' //  ok
// objCase = null  //  error
// objCase = undefined  //  error
// objCase = {}  //  ok

// let objCase2: object 
// objCase2 = 1  //  error
// objCase2 = 'str'  //  error
// objCase2 = null  //  error
// objCase2 = undefined  //  error
// objCase2 = {}  //  ok


// let num = 1
// i = 's' //error

// let flag
// flag = 1  // ok


// 联合类型
// let n : string | number
// n = ''
// n.toString()
// n = 1
// n.toFixed()

// n = {}  //error

// 类型断言

// let val = 'hello'
// let len:number = (val as string).length

// let flag: null | undefined | string
// (flag as string).toString()

// 字面量类型
// let flag : 'hello' = 'hello' // ok
// let flag : 'hello' = 'hellos'  //error
// let num: 1 | '2' = '2'

// interface A { 
//     a: string
// }
// interface A {
//     b: number
// }
// let C: A = {
//     a: '111',
//     b: 1
// }

// type flag = string | number

// function fn(val:flag) {

// }
// fn(true)  //error

// interface A { 
//     a: string
// }
// interface B {
//     b: number
// }

// type A = {
//     x: number
// }
// type B = A & {
//     y: string
// }
// let flag: B = {
//     x: 1,
//     y: 'hello',
// }

// interface Type1 {
//     func1(): void;
//     func2(): void;
// }

// interface Type2 {
//     func3(): void;
//     func2(): void;
// }

// const isType1 = (type: unknown): type is Type1 => (type as Type1).func1 === undefined
// function fn(val: Type1 | Type2) {
//     val.func2();
//     if (isType1(val)) {
//         val.func1();
//         val.func1();
//     }
// }
// interface Bird {
//     fly: number;
// }

// interface Dog {
//     leg: number;
// }

// function getNumber(value: Bird | Dog) {
//     if ("fly" in value) {
//         return value.fly;
//     }
//     return value.leg;
// }

// 函数声明
// function fn (val: string): number {
//     return val.length
// }

// const fn = (val: string): number => val.length

// type fnFunc = ( n?: number,val: string) => number
// const fn2: fnFunc = (val) => val.length

// fn2('ss')

// function fn(...arr: [string,number]) {
//     return arr.length
// }
// fn('1',1)

// function fn(x: string): string
// function fn(x: number): number
// function fn(x: string | number): string | number {
//     if(typeof x === 'string') {
//         return x.toString()
//     } else {
//         return x
//     }
// }

// class A {
//     public name: string
//     constructor(name: string) {
//         this.name = name
//     }
//     get myName() {
//         return this.name
//     }
//     set myName(v) {
//         this.name = v
//     }
//     speak() {
//         console.log(this.name)
//     }
// }
// class B extends A {
//     constructor(name: string) {
//         super(name)
//     }
// }
// const b = new B('hahaha')
// b.speak()

// abstract class C {
//     name!: string
//     constructor(name: string) {
//         this.name = name
//     }
//     abstract speak(): void
// }
// new C() //error

// class Cat extends C {
//     constructor(name: string) {
//         super(name)
//     }
//     speak() {
//         console.log(this.name)
//     }
// }
// const c = new Cat('cjq')
// c.speak()

// interface Person {
//     (name:string): string
// }

// const man:Person = function (name: string):string {
//     return name
// }


// class Animal {
//     name: string
//     constructor (name: string) {
//         this.name = name
//     }
// }

// interface nameClass {
//     new (name: string) : Animal
// }

// function createAnimal (classz:nameClass , name:  string) {
//     return new classz(name)
// }
// let m = createAnimal(Animal, 'cjq')

// interface Person {
//     name: string
// }
// interface Man extends Person {
//     age: number
// }

// type a = {
//     name: string
// }
// type b = a & {
//     age: number
// }
// type c = b & Person


// interface Wonmen extends c {

// }

// type A = {name: string} | {age: number}
// class B implements A { //error
//     name!: string
//     constructor() {}
// }

// function createArr<T>(len: number, val: T): T[] {
//     let arr: T[] = []
//     while (len--) arr.push(val)
//     return arr
// }
// createArr<string>(5, 'cjq')

// interface Lenght {
//     length: number
// }

// function getLen<T extends Lenght>(val: T): number {
//     return val.length

// }

// interface List<T> {
//     list: T[]
// }

// const arr: List<string> = { list: ['cjq', 'handsome'] }


// class Stack<T> {
//     private arr!: T[]

//     add(val: T) {
//         this.arr.push(val)
//     }

//     getMax():T {
//         let max = this.arr[0]
//         for(let v of this.arr) {
//             if(v > max) {
//                 max = v
//             }
//         }
//         return max
//     }
//  }


// const Person = {
//     name: 'cjq',
//     age: 18
// }
// type P = typeof Person

// interface Person {
//     name: string
//     age: number
// }
// type Man = {
//     [key in keyof Person]?: Person[key]
// }
// // type P = keyof Person

// // const a: P = 'name'

// // type x = Person["name"]

// type Flat<T> = T extends Array<infer U> ? U : any

// type T0 = [string, number]
// type T1 = Flat<T0> // string | number

// namespace a {
//     function addName(constructor: Function) {
//         constructor.prototype.name = 'cjq'
//         constructor.prototype.eat = function(){
//             console.log(this.name)
//         }
//     }
//     @addName
//     class A {
//         name!: string
//         eat!: () => void
//     }

//     const a = new A()
//     a.name
//     a.eat()
// }

// function upperCase(target: any, propertyKey: string) {
//     let value = target[propertyKey];
//     const getter = function () {
//       return value;
//     };
//     // 用来替换的setter
//     const setter = function (newVal: string) {
//       value = newVal.toUpperCase();
//     };
//     // 替换属性，先删除原先的属性，再重新定义属性
//     if (delete target[propertyKey]) {
//       Object.defineProperty(target, propertyKey, {
//         get: getter,
//         set: setter,
//         enumerable: true,
//         configurable: true,
//       });
//     }
//   }

//   class Person {
//     @upperCase
//     name!: string;
//   }
//   let p: Person = new Person();
//   p.name = "world";
//   console.log(p.name);


//重写方法
function toNumber(
    target: any,
    methodName: string,
    descriptor: PropertyDescriptor
) {
    // console.log(descriptor)
    // let oldMethod = descriptor.value;
    // descriptor.value = function (...args: any[]) {
    //     args = args.map((item) => parseFloat(item));
    //     return oldMethod.apply(this, args);
    // };
}
// class Person {
//     name: string = "hello";
//     public static age: number = 10;
//     constructor() { }
//     getName() {
//         console.log(this.name);
//     }
//     @toNumber
//     sum(...args: any[]) {
//         return args.reduce((accu: number, item: number) => accu + item, 0);
//     }
// }
// let p: Person = new Person();
// for (let attr in p) {
//     console.log("attr=", attr);
// }
// p.getName();

// function a () {

// }
// console.log(p.sum("1", "2", "3"));
// type Exclude<T, U> = T extends U ? never : T;

// interface P {
//     name: string,
//     age: number
// }
// interface B {
//     name: string,
//     age: number
// }
function getName(name: string) {
    return name
}
interface Person {
    name: string
    age?: number
}
type Man = {
    name: string
    age?: number
}
//排除第二个参数
type E = Exclude<string | number, string>
//只留第二个参数
type R = Extract<string | number, string>
//获取函数的返回值类型
type F = ReturnType<typeof getName>
//排除空和undefined
type W = NonNullable<string | number | null | undefined>
//获取函数的参数类型
type A = Parameters<typeof getName>
//把非可选改成可选
type C = Partial<Person>
//把可选变成必选
type D = Required<Person>
//把全部属性变为只读
type V = Readonly<Person>
//取某些属性返回
type G = Pick<Man,'age'>
//重组key，value
type S = Record<'x', Man>
//剔除类型，获取新的类型
type H = Omit<Person, 'name'>